<?php

declare(strict_types=1);
/**
 * This file is part of habo_new_media.
 *
 * @link     https://www.berlen.cn/
 * @contact  tech@berlen.cn
 * @license  http://gitlab.rehou.cn/habo/habo_new_media/-/blob/master/README.md
 */
namespace app\service\batch\kuaishou;

use app\enum\BatchProjectEnum;
use app\enum\KuaiShouEnum;
use app\model\BatchProjectContentModel;
use app\model\BatchProjectModel;
use app\model\KsBatchProjectModel;
use app\model\KsCampaignDspModel;
use app\service\batch\BatchService;
use app\service\build\kuaishou\AttrService;
use app\service\build\kuaishou\BatchService as BuildService;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;

/**
 * 智能化2.0创建结构体.
 */
final class CreateContentService extends BatchService
{
    /**
     * @var null|BuildService 搭建服务类
     */
    public ?BuildService $buildService;

    public array $campaignIds = [];

    public array $unitIds = [];

    public array $creativeIds = [];

    /**
     * @var null|AttrService 搭建属性服务类
     */
    protected ?AttrService $attrService;

    /**
     * 生成结构体.
     * @param KsBatchProjectModel $model 搭建数据模型
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function createContent(KsBatchProjectModel $model): bool
    {
        if ($model->getAttr('status') != KuaiShouEnum::BATCH_STATUS_WAIT && $model->getAttr('status') != -1) {
            return self::setError('搭建状态有误');
        }
        $this->attrService = new AttrService();
        if (! $this->attrService->initService($model->getKey())) {
            return self::setError('初始化项目失败');
        }
        $this->buildService = $this->attrService->batch;
        $batchProject = self::getBatchProject($model->getAttr('batch_project_id'));
        if (! $batchProject instanceof BatchProjectModel) {
            return self::setError('获取batch_project数据失败');
        }
        // 生成广告计划结构体
        $this->campaignIds = $campaignIds = self::campaignContent();
        if (! $campaignIds) {
            return self::setError('生成广告计划结构体失败');
        }
        // 广告组
        $this->unitIds = $units = self::unitContent($campaignIds);
        if (! $units) {
            return self::setError('生成广告组结构体失败');
        }
        // 广告创意
        $this->creativeIds = $creativeIds = self::creativeContent($units);
        if (! $creativeIds) {
            return self::setError('生成广告创意结构体失败');
        }
        // 修改状态
        $model->setAttr('status', BatchProjectEnum::PROJECT_STATUS_CONTENT_SUCCESS);
        if (! $model->save()) {
            return self::setError('更新主表状态失败');
        }
        return true;
        // 加入处理素材的队列 && 广告计划队列
        //        if ($this->buildService->isNewCampaign()) {
        //            // 已建计划直接执行组
        //            self::pushKsCampaignList($campaignIds);
        //        } else {
        //            self::pushKsUnitList(array_column($units, 'id'));
        //        }
        //        return self::pushKsMaterialList($creativeIds);
    }

    /**
     * 生成广告计划结构体.
     */
    private function campaignContent(): array
    {
        $resultIds = [];
        $advertiserId = $this->buildService->getAdvertiserId();
        $content = [
            'advertiser_id' => $advertiserId,
            'account_id' => $this->buildService->getBatchAccountId(),
            'client_id' => $this->buildService->getClientId(),
            'batch_project_id' => $this->buildService->getBatchAttr('batch_project_id'),
            'content_level' => $this->attrService->getCampaignLevel(),
            'project_id' => $this->buildService->getBatchId(),
        ];
        if ($this->buildService->isNewCampaign()) {
            // 获取已搭建的广告计划数量
            $this->buildService->setCampaignBuildNum();
            for ($i = 1; $i <= $this->buildService->getBatchAttr('campaign_num'); ++$i) {
                $this->buildService->setCampaignNum();
                $campaignInfo = [
                    'advertiser_id' => $advertiserId,
                    'campaign_name' => $this->attrService->getCampaignName(),
                    'type' => $this->buildService->getCampaignType(),
                    'auto_adjust' => $this->buildService->getCampaignAttr('auto_adjust'),
                    'auto_build' => $this->buildService->getCampaignAttr('auto_build'),
                    'auto_manage' => $this->buildService->getCampaignAttr('auto_manage'),
                    'day_budget' => 0,
                    'day_budget_schedule' => [],
                    'is_open' => $this->buildService->getIsOpen(),
                ];
                if ($campaignInfo['auto_build'] == KuaiShouEnum::AUTO_BUILD_OPEN) {
                    // 自动基建
                    $campaignInfo['auto_build_name_rule'] = [
                        'unit_name_rule' => $this->attrService->getAutoUnitName(),
                        'creative_name_rule' => $this->attrService->getAutoCreativeName(),
                    ];
                }
                $content['content'] = json_encode($campaignInfo, JSON_UNESCAPED_UNICODE);
                $resultIds[] = self::saveContentData($content);
            }
        } else {
            // 选择已建计划直接设置成功状态
            $content['return_api_id'] = $this->buildService->getUnitAttr('campaign_id');
            $content['status'] = BatchProjectEnum::STATUS_SUCCESS;
            $campaignName = (new KsCampaignDspModel())->where('campaign_id', $content['campaign_id'])->value('campaign_name');
            $campaignInfo = [
                'advertiser_id' => $advertiserId,
                'campaign_name' => $campaignName,
                'type' => $this->buildService->getCampaignType(),
                'day_budget' => 0,
                'day_budget_schedule' => [],
            ];
            $content['content'] = json_encode($campaignInfo, JSON_UNESCAPED_UNICODE);
            $resultIds[] = self::saveContentData($content);
        }
        return $resultIds;
    }

    /**
     * 生成广告組结构体.
     * @param array $campaignIds 計劃id
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    private function unitContent(array $campaignIds = []): array
    {
        $advertiserId = $this->buildService->getAdvertiserId();
        $campaignType = $this->buildService->getCampaignType();
        $results = [];
        $this->buildService->resetCampaignNum();
        // 获取已搭建的广告组数量
        $this->buildService->setUnitBuildNum();
        foreach ($campaignIds as $campaignId) {
            $this->buildService->setCampaignNum();
            for ($j = 1; $j <= $this->buildService->getBatchAttr('unit_num'); ++$j) {
                $this->buildService->setUnitNum();
                $cpaBid = $this->attrService->getBid();
                // 查询转化名
                $unitInfo = [
                    'advertiser_id' => $advertiserId,
                    'unit_name' => $this->attrService->getUnitName(),
                    //                    'template_id' => $this->attrService->getTemplateId(),
                    'target' => $this->attrService->getTemplateStruck(),
                    'bid_type' => $this->buildService->getBidType(),
                    'cpa_bid' => $cpaBid,
                    'ocpx_action_type' => $this->buildService->getOcpxActionType(),
                    'scene_id' => $this->buildService->getSceneId(),
                    'unit_type' => $this->attrService->getUnitType(),
                    'smart_cover' => $this->attrService->getSmartCover(), // 智能抽针
                    'asset_mining' => $this->attrService->getAssetMining(), // 素材挖掘
                    'begin_time' => $this->buildService->getBeginTime(),
                    'day_budget' => 0,
                    'show_mode' => $this->buildService->getUnitAttr('show_mode'),
                ];

                // 应用下载方式
                $appDownloadType = $this->buildService->getAppDownloadType();
                if ($this->buildService->isAppType()) {
                    // 提升应用安装
                    $unitInfo['app_id'] = $this->buildService->getAppId();
                    // 新版应用获取应用包ID
                    if ($this->buildService->getAppType() == KuaiShouEnum::APP_SOURCE_NEW) {
                        $unitInfo['package_id'] = $this->attrService->getPackageId();
                    }

                    // 直达链接
                    if ($this->attrService->getSchemaUri()) {
                        $unitInfo['schema_uri'] = $this->attrService->getSchemaUri();
                    }

                    if ($campaignType == KuaiShouEnum::CAMPAIGN_TYPE_INSTALL) {
                        // 应用商店
                        if ($this->attrService->isUseAppMarket()) {
                            $unitInfo['use_app_market'] = $this->buildService->getUnitAttr('use_app_market');
                            $unitInfo['app_store'] = $this->buildService->getUnitAttr('app_store');
                        }

                        // 应用下载方式
                        if ($appDownloadType != -1) {
                            $unitInfo['app_download_type'] = $appDownloadType;
                        }

                        // 落地页ID
                        $downloadPageId = $this->buildService->getDownloadPageId();
                        if (! empty($downloadPageId)) {
                            $unitInfo['site_id'] = $downloadPageId;
                        }
                    }

                    if ($campaignType == KuaiShouEnum::CAMPAIGN_TYPE_ACTIVE) {
                        $unitInfo['web_uri_type'] = $this->buildService->getWebUriType();
                        if ($unitInfo['web_uri_type'] == KuaiShouEnum::WEB_URI_TYPE_SET) {
                            $unitInfo['site_id'] = $this->attrService->getLpId();
                        }
                        if ($unitInfo['web_uri_type'] == KuaiShouEnum::WEB_URI_TYPE_CUSTOM) {
                            $unitInfo['url'] = $this->attrService->getUrl();
                        }
                    }
                } elseif ($campaignType == KuaiShouEnum::CAMPAIGN_TYPE_SALE) {
                    // 销售线索收集
                    $landingPageArr = $this->attrService->getLandingTemplate();
                    $unitInfo['url'] = $landingPageArr['landing_url'] ?? '';
                    $unitInfo['schema_uri'] = $this->attrService->getSchemaUrl();
                    // 建站落地页
                    if ($this->buildService->getLandingPage() == KuaiShouEnum::LP_LANDING_TEMPLATE && ! empty($this->attrService->getSiteId())) {
                        $unitInfo['web_uri_type'] = KuaiShouEnum::WEB_URI_TYPE_SET;
                        // 随机取一个
                        $unitInfo['site_id'] = $this->attrService->getSiteId();
                    }
                }

                // 深度优化目标
                if ($this->buildService->getDeepConversionType()) {
                    $unitInfo['deep_conversion_type'] = $this->buildService->getDeepConversionType();
                    $unitInfo['deep_conversion_bid'] = $this->attrService->getDeepBid();
                }
                // 试玩库
                if (! empty($this->buildService->getUnitAttr('playable_id')) && ! empty($this->buildService->getUnitAttr('play_button'))) {
                    $unitInfo['playable_id'] = $this->buildService->getUnitAttr('playable_id');
                    $unitInfo['play_button'] = $this->buildService->getUnitAttr('play_button');
                }
                // 增强目标
                if ($this->buildService->getPromotionRange() != KuaiShouEnum::PROMOTION_RANGE_KS && $this->buildService->getDeepConversionType() == KuaiShouEnum::DEEP_CONVERSION_TYPE_CRLC && ! empty($this->buildService->getEnhanceConversionType())) {
                    $unitInfo['enhance_conversion_type'] = $this->buildService->getEnhanceConversionType();
                }
                // 排期
                if ($this->buildService->getLaunchType() != KuaiShouEnum::LAUNCH_TYPE_ALWAYS) {
                    $unitInfo['end_time'] = $this->buildService->getEndTime();
                }
                // 投放时间段
                $unitInfo['schedule_time'] = $this->attrService->getScheduleTime();
                // 随机卡片
                if ($this->buildService->getAdvCardOption() == KuaiShouEnum::ADV_CARD_OPTION_OPEN) {
                    $unitInfo['adv_card_option'] = $this->buildService->getAdvCardOption();
                    $unitInfo['adv_card_list'] = $this->attrService->getAdvCard();
                    $unitInfo['card_type'] = $this->buildService->getCardType();
                }

                // 搜索块投
                if ($this->buildService->getUnitAttr('quick_search') == KuaiShouEnum::QUICK_SEARCH_OPEN) {
                    $unitInfo['quick_search'] = $this->buildService->getUnitAttr('quick_search');
                    $unitInfo['extend_search'] = true;
                    $unitInfo['target_explore'] = $this->buildService->getUnitAttr('target_explore');
                }

                // 付费roi
                if (in_array($this->buildService->getOcpxActionType(), [KuaiShouEnum::ACTION_TYPE_SEVEN_ROI, KuaiShouEnum::ACTION_TYPE_FIRST_ROI])) {
                    $unitInfo['roi_ratio'] = $this->attrService->getRoiRatio();
                    unset($unitInfo['cpa_bid']);
                }
                if ($this->buildService->getDeepConversionType() == KuaiShouEnum::DEEP_CONVERSION_ROI) {
                    $unitInfo['roi_ratio'] = $this->attrService->getDeepRoiRatio();
                    unset($unitInfo['deep_conversion_bid']);
                }
                // 是否开启原生
                $unitInfo['outer_loop_native'] = $this->buildService->getOuterLoopNative();
                // 商品数据
                if ($this->buildService->getProductId() && $this->attrService->setProduct()) {
                    $unitInfo['dpa_unit_param'] = [
                        'dpa_unit_sub_type' => $this->attrService->getDpaUnitSubType(),
                        'library_id' => $this->attrService->getLibraryId(),
                        'product_id' => $this->attrService->getProductId(),
                        'outer_id' => $this->attrService->getOuterId(),
                    ];
                }

                $content['content'] = json_encode($unitInfo, JSON_UNESCAPED_UNICODE);
                $content['parent_id'] = $campaignId;
                $content['advertiser_id'] = $advertiserId;
                $content['account_id'] = $this->buildService->getBatchAccountId();
                $content['client_id'] = $this->buildService->getClientId();
                $content['content_level'] = $this->attrService->getUnitLevel();
                $content['project_id'] = $this->buildService->getBatchId();
                $content['batch_project_id'] = $this->buildService->getBatchAttr('batch_project_id');

                $results[] = [
                    'id' => self::saveContentData($content),
                    'code' => $this->attrService->getSchemaCode(),
                    'campaign_num' => $this->buildService->getCampaignNum(),
                ];
            }
        }
        return $results;
    }

    /**
     * 生成广告创意结构体.
     * @param array $units 组数据
     * @return array
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    private function creativeContent(array $units = []): array
    {
        $advertiserId = $this->buildService->getAdvertiserId();
        $i = 0;
        $resultIds = [];
        $this->buildService->resetUnitNum();
        $this->buildService->resetCreativeNum();
        foreach ($units as $unit) {
            $content = [
                'parent_id' => $unit['id'],
                'advertiser_id' => $advertiserId,
                'account_id' => $this->buildService->getBatchAccountId(),
                'client_id' => $this->buildService->getClientId(),
                'content_level' => $this->attrService->getCreativeLevel(),
                'project_id' => $this->buildService->getBatchId(),
                'batch_project_id' => $this->buildService->getBatchAttr('batch_project_id'),
            ];
            $this->buildService->setUnitNum();
            $this->buildService->resetCampaignNum($unit['campaign_num']);
            if ($this->buildService->getCreativeType() == KuaiShouEnum::CREATIVE_TYPE_CUSTOM) {
                // 自定义创意
                for ($l = 1; $l <= $this->buildService->getBatchAttr('creative_num'); ++$l) {
                    $this->buildService->setCreativeNum();
                    $creativeInfo = self::getCustomCreative();
                    $content['content'] = json_encode($creativeInfo, JSON_UNESCAPED_UNICODE);
                    $resultIds[] = self::saveContentData($content);
                    ++$i;
                }
            } else {
                $this->buildService->setCreativeNum();
                // 程序化创意
                $creativeInfo = self::getProgramCreative();
                $content['content'] = json_encode($creativeInfo, JSON_UNESCAPED_UNICODE);
                $resultIds[] = self::saveContentData($content);
                ++$i;
            }
        }
        return $resultIds;
    }

    /**
     * 获取广告自定义创意结构体.
     * @return array
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    private function getCustomCreative(): array
    {
        $advertiserId = $this->buildService->getAdvertiserId();
        $creativeInfo['creative_type'] = $this->buildService->getCreativeType();
        $creativeInfo['advertiser_id'] = $advertiserId;
        // 创意分类标签
        $creativeCategory = $this->attrService->getCreativeCategory();
        if (! empty($creativeCategory)) {
            if (! empty($creativeCategory['creative_category'])) {
                $creativeInfo['creative_category'] = end($creativeCategory['creative_category']) ?? '';
            }
            $creativeInfo['creative_tag'] = $creativeCategory['tags'] ?? '';
        }
        $creativeInfo['is_system'] = $this->buildService->getIsSystem();
        $creativeInfo['video_sticker_style_id'] = 0;
        $creativeInfo['video_sticker_style_overlay_type'] = 0;
        $creativeInfo['video_sticker_title'] = '';
        $creativeInfo['note_pic_id'] = '';
        $creativeInfo['note_short_slogan'] = '';
        $creativeInfo['action_bar_text'] = $this->attrService->getActionBarText();
        $creativeInfo['description'] = $this->attrService->getDescription();
        $creativeInfo['click_track_url'] = $this->attrService->getClickTrackUrl();
        $creativeInfo['actionbar_click_url'] = $this->attrService->getActionbarClickUrl();
        $creativeInfo['impression_url'] = $this->attrService->getImpressionUrl();
        // 是否开启原生
        $creativeInfo['outer_loop_native'] = $this->buildService->getOuterLoopNative();
        if ($creativeInfo['outer_loop_native']) {
            $creativeInfo['kol_user_type'] = $this->buildService->getCreativeAttr('kol_user_type');
            $creativeInfo['kol_user_id'] = $this->buildService->getCreativeAttr('kol_user_id');
            // 原生PLC描述语
            $creativeInfo['recommendation'] = $this->buildService->getCreativeAttr('recommendation');
        }
        if (! empty($this->attrService->getVideoList())) {
            // 视频素材搭建
            $creativeInfo['photo_ids'] = [$this->attrService->getCurrentCustomVideo()];
            $creativeInfo['creative_material_type'] = $this->attrService->getVideoType();
            $creativeInfo['creative_name'] = $this->attrService->getCurrentVideoCreativeName();
        } elseif (! empty($this->attrService->getPicList())) {
            // 图片素材
            $creativeInfo['image_tokens'] = [$this->attrService->getCurrentCustomPic()];
            $creativeInfo['creative_material_type'] = $this->attrService->getPicType();
            $creativeInfo['creative_name'] = $this->attrService->getPicCreativeName();
        }
        return $creativeInfo;
    }

    /**
     * 获取广告程序化创意结构体.
     * @return array
     */
    private function getProgramCreative(): array
    {
        $advertiserId = $this->buildService->getAdvertiserId();
        $creativeInfo = [];
        // 广告语
        $creativeInfo['captions'] = $this->attrService->getDescription();
        if ($this->buildService->getPromotionRange() == KuaiShouEnum::PROMOTION_RANGE_KS) {
            $creativeInfo['pic_list'] = $this->attrService->getCurrentProgramPic();
        }
        $creativeInfo['advertiser_id'] = $advertiserId;
        $creativeInfo['creative_type'] = KuaiShouEnum::CREATIVE_TYPE_PROGRAM;
        $creativeInfo['package_name'] = $this->attrService->getCreativeName();
        $creativeInfo['photo_ids'] = $this->attrService->getCurrentProgramVideo();
        $creativeInfo['sticker_styles'] = $this->buildService->getStickerStyles();
        $creativeInfo['cover_slogans'] = $this->buildService->getCoverSlogans();
        // 检测链接
        $creativeInfo['click_url'] = $this->attrService->getClickTrackUrl();
        $creativeInfo['actionbar_click_url'] = $this->attrService->getActionbarClickUrl();
        $creativeInfo['is_system'] = $this->buildService->getIsSystem();
        // 是否开启原生
        $creativeInfo['outer_loop_native'] = $this->buildService->getOuterLoopNative();
        if (! empty($creativeInfo['outer_loop_native'])) {
            $creativeInfo['kol_user_type'] = $this->buildService->getCreativeAttr('kol_user_type');
            $creativeInfo['kol_user_id'] = $this->buildService->getCreativeAttr('kol_user_id');
            // 原生PLC描述语
            $creativeInfo['recommendation'] = $this->buildService->getCreativeAttr('recommendation');
        }
        $creativeCategory = $this->attrService->getCreativeCategory();
        if (! empty($creativeCategory)) {
            if (! empty($creativeCategory['creative_category'])) {
                $creativeInfo['creative_category'] = end($creativeCategory['creative_category']) ?? '';
            }
            $creativeInfo['creative_tag'] = $creativeCategory['tags'] ?? '';
        }
        $creativeInfo['action_bar'] = $this->attrService->getActionBarText();

        return $creativeInfo;
    }

    /**
     * 存结构体数据.
     * @param array $params 参数
     * @return int|string
     */
    private static function saveContentData(array $params = [])
    {
        $params['create_time'] = time();
        return (new BatchProjectContentModel())->insertGetId($params);
    }

    /**
     * 获取搭建主表数据.
     * @param int $id id
     * @return mixed
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    private static function getBatchProject(int $id = 0)
    {
        return (new BatchProjectModel())->where('id', $id)->find();
    }
}
